package com.dayu.structure.flyweight;

/**
 * 享元模式：减少创建对象的数量，以减少内存占用和提高性能。
 * 享元模式尝试重用现有的同类对象，如果未找到匹配的对象，则创建新对象
 * 在有大量对象时，有可能会造成内存溢出，我们把其中共同的部分抽象出来，如果有相同的业务请求，直接返回在内存中已有的对象，避免重新创建。
 */

/**
 * 其实很多小伙伴疑惑的是享元模式和原型模式的区别：
 * 原型模式是在创建多个实例的时候，对创建过程的性能进行调优
 * 享元模式是用减少创建实例的方式，来调节系统性能
 * 有些场景需要重复创建多个实例，例如在循环中赋值一个对象，此时我们就可以采用原型模式来优化对象的创建过程
 * 有些场景下，我们可以避免重复创建多个实例，在内存中共享对象就可以了
 */

/**
 * 享元模式中存在以下两种状态：
 *
 * 内部状态，即不会随着环境的改变而改变的可共享部分；
 * 外部状态，指随环境改变而改变的不可以共享的部分。享元模式的实现要领就是区分应用中的这两种状态，并将外部状态外部化。下面来分析其基本结构和实现方法。
 */
public class FlyweightTest {

    /**
     *  1、系统中有大量对象。
     *  2、这些对象消耗大量内存。
     *  3、这些对象的状态大部分可以外部化。
     *  4、这些对象可以按照内蕴状态分为很多组，当把外蕴对象从对象中剔除出来时，每一组对象都可以用一个对象来代替。
     *  5、系统不依赖于这些对象身份，这些对象是不可分辨的。
     */

    /**
     * 应用实例：
     * 1、JAVA 中的 String，如果有则返回，如果没有则创建一个字符串保存在字符串缓存池里面。
     * 2、数据库的数据池。
     * 3、Integer的valueOf以及Boolean、Byte、Character、Short、Long、BigDecimal
     */

    /**
     * 享元模式的角色如下：
     * 抽象享元角色（Flyweight）：是所有的具体享元类的基类，为具体享元规范需要实现的公共接口，非享元的外部状态以参数的形式通过方法传入。
     * 具体享元（Concrete Flyweight）角色：实现抽象享元角色中所规定的接口。
     * 非享元（Unsharable Flyweight)角色：是不可以共享的外部状态，它以参数的形式注入具体享元的相关方法中。
     * 享元工厂（Flyweight Factory）角色：负责创建和管理享元角色。当客户对象请求一个享元对象时，享元工厂检査系统中是否存在符合要求的享元对象，如果存在则提供给客户；如果不存在的话，则创建一个新的享元对象。
     */
    /**
     * 五子棋：
     * 棋子是抽象享元角色
     * 白色棋子、黑色棋子是具体享元的角色
     * 棋子的位置是非享元角色
     * 棋子盒子：可以认为是享元工厂，我们在这里拿黑棋子和白棋子
     */
}
